<template>
  <h2>{{ obj1 }}</h2>
  <button @click="change">change</button>
</template>
<script setup lang="ts">
import { reactive, toRaw, toRef, toRefs } from 'vue'

// toRef 第一个参数为响应式对象,第二个参数为对象的属性,类型为字符串,返回值为 Ref 对象
// 即对该对象的该属性调用 ref 方法
// const refObj: Ref = toRef(obj: Proxy || Ref, property: string)

// toRefs 参数为响应式对象，返回值为一普通对象包裹的将各个属性调用 toRef 方法
// 即迭代每个属性，依次对每个属性调用 toRef
// const obj: { property: Ref } = toRefs(obj: Proxy || Ref)

// toRef 和 toRefs 常用于将响应式对象进行解构,提取出对象的属性数据并转化为响应式
// toRef 和 toRefs 返回的响应式对象与 ref 返回的对象具有一定差别
// 实质为 toRef 和 toRefs 未增加响应式操作(track, trigger),故参数未非响应式数据时无反应
// 避免对 toRef 和 toRefs 返回的对象多次调用 track 和 trigger

// toRaw 参数为响应式数据(对象或原始类型),返回值为一普通值,即解除了响应式
// 实质是通过将响应式对象的 __v_Raw 属性访问到原始值并将其返回
// const newval = toRaw(val: Proxy || Ref)

const obj = {
  name: 'Tom',
  age: 20,
  friend: {
    name: 'Jerry',
    age: 18,
  },
}
const obj1 = reactive(obj)
// toRef 对一般的对象无效
// toRef 返回值为 Ref 对象,可以将响应式对象中的某个属性提取出来,将属性值调用 ref 方法
// 该属性可以为 Object 类型,实质也是对 Object 对象调用 ref 方法
// const name = toRef(obj1, 'name')
// const friend = toRef(obj1, 'friend')
// toRefs 实质是迭代响应式对象的每个属性,在每个属性上调用 toRef 方法
const MyToRefs = <T extends object>(obj: T) => {
  const map: any = {}
  for (let key in obj) {
    map[key] = toRef(obj, key)
  }
  return map
}
const { name, age, friend } = toRefs(obj1)
const change = () => {
  // name.value += '='
  // console.log(name)
  // friend.value.name += '='
  // console.log(friend.value)
  // console.log(name)
  // console.log(age)
  // console.log(friend)
  console.log(obj1,toRaw(obj1.friend))
}
</script>
<style scoped></style>
